<?php

namespace Biz\service;

use Biz\cache\Shipping as cShipping;
use Biz\model\GoodsBasicInfo;
use Biz\model\GoodsExtendInfo;
use Biz\model\ShippingTempl as ShippingTemplModel;
use Biz\model\ShippingTemplAttr as ShippingTemplAttrModel;
use Biz\service\trade\UserAddress as UserAddress;
use Biz\tools\ShopArea;
use Doraemon\tools\Log;
/**
 * @deprecated
 */
class ShippingTempl
{

    /**
     * 获取商品的邮费
     * @param $shopId
     * @param array $goodsAllNumAndWeight ['goods_id'=>['sku_id'=>['shipping_templ_id'=>309,'buy_num'=>'总数量','weight'=>'总重量','volume'=>'总体积']],'goods_id'=>['sku_id'=>['shipping_templ_id'=>400,'buy_num'=>'总数量','weight'=>'总重量','volume'=>'总体积']]]
     * @param $areaCode
     * @return array
     * @throws \Exception
     */
    public static function getShippingFee($shopId, array $goodsAllNumAndWeight, $areaCode)
    {
        $result = [
            'price' => 0,
            'templ_price' => [],
            'sku_price' => []
        ];
        //运费模版分组
        $templIds = [];
        $templGoods = [];
        Log::info('计算运费', compact('goodsAllNumAndWeight'));
        foreach ($goodsAllNumAndWeight as $goodsId => $goodsArr) {
            foreach ($goodsArr as $skuId => $row) {
                $templId = $row['shipping_templ_id'];
                $templIds[] = $templId;
                if (!$templId) {
                    Log::error('计算运费,不存在的运费模版id：' . $templId . '#' . '#goods_id' . $goodsId . '#sku_id' . $skuId . json_encode($row));
                    throw new \Exception('系统错误');
                }

                if (!isset($templGoods[$templId])) {
                    $templGoods[$templId] = [
                        'buy_num' => 0,
                        'weight' => 0,
                        'volume' => 0,
                    ];
                }
                $templGoods[$templId]['buy_num'] += $row['buy_num'];
                $templGoods[$templId]['weight'] += $row['weight'];
                $templGoods[$templId]['volume'] += isset($row['volume']) ? $row['volume'] : 0;

                $templGoods[$templId]['sku_infos'][$skuId] = [
                    'sku_id' => $skuId,
                    'buy_num' => $row['buy_num'],
                    'weight' => $row['weight'],
                    'volume' => $row['volume'],
                ];
            }
        }
        $areaCodeArr = ShopArea::getAreaCodeArr($areaCode);
        $provinceCode = $areaCodeArr[0];
        $cityCode = $areaCodeArr[1];
        $tempIds = array_unique($templIds);
        $shopTemplList = self::getTemplByIds($templIds);

        foreach ($templGoods as $templId => $row) {
            $templSkuInfos = $templGoods[$templId]['sku_infos'];
            $buy_num = $row['buy_num'];
            $weight = $row['weight'];
            $volume = isset($row['volume']) ? $row['volume'] : 0;
            $templInfo = $shopTemplList[$templId];
            $templInfoAttr = $templInfo['attr'];
            $price = 0;
            $attrInfo = [];
            if($templInfoAttr && is_array($templInfoAttr)) {
                foreach ($templInfoAttr as $row) {
                    if ($row['is_default']) {//默认运费方案
                        $attrInfo = $row;
                    }
                    if ($areaCode) {
                        $area = explode(',', $row['area']);
                        if (in_array($areaCode, $area)) {
                            $attrInfo = $row;
                            break;
                        } else if (in_array($cityCode, $area)) {
                            $attrInfo = $row;
                            break;
                        } else if (in_array($provinceCode, $area)) {
                            $attrInfo = $row;
                            break;
                        }
                    } else {
                        if ($attrInfo) {
                            break;
                        }
                    }
                }
            }

            if ($attrInfo['type'] == 1 && $attrInfo['base_price'] == 0 && $attrInfo['continued_price'] == 0) {//包邮
                $price = 0;
            } else {
                if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_PIECES) {//按件计算
                    if ($buy_num <= $attrInfo['base'] || $attrInfo['base'] == 0) {
                        $price = $attrInfo['base_price'];
                    } else {
                        if ($attrInfo['continued'] > 0) {
                            $price = $attrInfo['base_price'];
                            $continue = ceil(bcadd(($buy_num - $attrInfo['base']) / $attrInfo['continued'], 0, 2));
                            $continuePrice = bcmul($continue, $attrInfo['continued_price'], 2);
                            $price = bcadd($price, $continuePrice, 2);
                        } else {
                            $price = $attrInfo['base_price'];
                            $price = bcadd($price, $attrInfo['continued_price'], 2);
                        }
                    }
                }
                if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_WEIGHT) {//按重量计算
                    if ($weight <= $attrInfo['base'] || $attrInfo['base'] == 0) {
                        $price = $attrInfo['base_price'];
                    } else {
                        if ($attrInfo['continued'] > 0) {
                            $price = $attrInfo['base_price'];
                            $continue = ceil(bcadd(($weight - $attrInfo['base']) / $attrInfo['continued'], 0, 2));
                            $continuePrice = bcmul($continue, $attrInfo['continued_price'], 2);
                            $price = bcadd($price, $continuePrice, 2);
                        } else {
                            $price = $attrInfo['base_price'];
                            $price = bcadd($price, $attrInfo['continued_price'], 2);
                        }
                    }
                }
                if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_VOLUME) {//按体积计算
                    if ($volume <= $attrInfo['base'] || $attrInfo['base'] == 0) {
                        $price = $attrInfo['base_price'];
                    } else {
                        if ($attrInfo['continued'] > 0) {
                            $price = $attrInfo['base_price'];
                            $continue = ceil(bcadd(($volume - $attrInfo['base']) / $attrInfo['continued'], 0, 2));
                            $continuePrice = bcmul($continue, $attrInfo['continued_price'], 2);
                            $price = bcadd($price, $continuePrice, 2);
                        } else {
                            $price = $attrInfo['base_price'];
                            $price = bcadd($price, $attrInfo['continued_price'], 2);
                        }
                    }
                }
            }
            $result['templ_price'][$templId] = $price;
            $result['price'] = bcadd($result['price'], $price, 2);

            //把数量或则重量、体积最大的排最后
            $skuSort = [];
            if($templSkuInfos && is_array($templSkuInfos)) {
                foreach ($templSkuInfos as $skuId => $skuInfo) {
                    if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_PIECES) {//按件计算
                        $skuSort[] = $skuInfo['buy_num'];
                    }
                    if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_WEIGHT) {//按重量计算
                        $skuSort[] = $skuInfo['weight'];
                    }
                    if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_VOLUME) {//按体积计算
                        $skuSort[] = $skuInfo['volume'];
                    }
                }
                array_multisort($skuSort, SORT_ASC, $templSkuInfos);
            }

            $i = 0;
            $skuCount = count($templSkuInfos);
            $skuTotalPrice = 0;
            foreach ($templSkuInfos as $skuInfo) {
                $skuId = $skuInfo['sku_id'];
                $result['sku_price'][$skuId]['shipping_templ_id'] = $templId;
                $result['sku_price'][$skuId]['price'] = 0;
                if ($price == 0) {
                    $result['sku_price'][$skuId]['price'] = 0;
                } else {
                    if ($i < $skuCount - 1) {
                        if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_PIECES) {//按件计算
                            $skuPrice = round(($skuInfo['buy_num'] / $buy_num) * $price, 2);
                            $result['sku_price'][$skuId]['price'] = $skuPrice;
                            $skuTotalPrice = bcadd($skuTotalPrice, $skuPrice, 2);
                        }
                        if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_WEIGHT) {//按重量计算
                            $skuPrice = round(($skuInfo['weight'] / $weight) * $price, 2);
                            $result['sku_price'][$skuId]['price'] = $skuPrice;
                            $skuTotalPrice = bcadd($skuTotalPrice, $skuPrice, 2);
                        }
                        if ($templInfo['billing_cate'] == ShippingTemplModel::BILLING_CATE_VOLUME) {//按体积计算
                            $skuPrice = round(($skuInfo['volume'] / $volume) * $price, 2);
                            $result['sku_price'][$skuId]['price'] = $skuPrice;
                            $skuTotalPrice = bcadd($skuTotalPrice, $skuPrice, 2);
                        }
                    } else {
                        //最后一个sku的运费等于总运费减去前几个sku的总运费
                        $skuPrice = bcsub($price, $skuTotalPrice, 2);
                        $result['sku_price'][$skuId]['price'] = $skuPrice;
                        $skuTotalPrice = bcadd($skuTotalPrice, $skuPrice, 2);
                    }
                }
                $i++;
            }
            if (bccomp($price, $skuTotalPrice, 2) != 0) {
                throw new \Exception('商品运费计算错误');
            }
        }
        Log::info('计算运费', compact('shopId', 'goodsAllNumAndWeight', 'areaCode', 'result'));
        return $result;
    }

    public static function getTempl($shopId, $attr = true)
    {
        $list = [];
        $tempList = ShippingTemplModel::getTempl($shopId, ShippingTemplAttrModel::STATUS_PASSED);
        if ($tempList && $attr) {
            $tempIds = array_column($tempList, 'id');
            $attrArr = ShippingTemplAttrModel::getByTemplId($tempIds, ShippingTemplAttrModel::STATUS_PASSED, ['is_default' => 'DESC']);
            $attrList = [];
            foreach ($attrArr as $row) {
                $attrList[$row['templ_id']][] = $row;
            }
            foreach ($tempList as $row) {
                if (isset($attrList[$row['id']])) {
                    $row['attr'] = $attrList[$row['id']];
                } else {
                    $row['attr'] = [];
                }
                $list[$row['id']] = $row;
            }
        } else {
            $list = $tempList;
        }
        return $list;
    }

    public static function getTemplByIds($tempIds)
    {
        $list = [];
        $tempList = ShippingTemplModel::getTemplByIds($tempIds, ShippingTemplAttrModel::STATUS_PASSED);
        if ($tempList) {
            $attrArr = ShippingTemplAttrModel::getByTemplId($tempIds, ShippingTemplAttrModel::STATUS_PASSED, ['is_default' => 'DESC']);
            $attrList = [];
            foreach ($attrArr as $row) {
                $attrList[$row['templ_id']][] = $row;
            }
            foreach ($tempList as $row) {
                if (isset($attrList[$row['id']])) {
                    $row['attr'] = $attrList[$row['id']];
                } else {
                    $row['attr'] = [];
                }
                $list[$row['id']] = $row;
            }
        }
        return $list;
    }

    /**
     * 编辑模板信息
     * @param $uid
     * @param $shopId
     * @param $name
     * @param $billingCate
     * @param $billingUit
     * @param $shippingPlace
     * @param $supportArea
     * @param $shippingPrice
     * @param int $templId
     * @return bool
     * @throws \Exception
     */
    public static function editTempl($uid, $shopId, $name, $billingCate, $billingUit, $shippingPlace, $supportArea, $shippingPrice, $templId = 0)
    {
        $shippingPrice = json_decode($shippingPrice, true);
        $checkAreaArr = [];
        foreach ($shippingPrice as $row) {
            $areas = self::implodeAreaCode($row['area'], false);
            if (!array_intersect($areas, $checkAreaArr)) {
                $checkAreaArr = array_merge($checkAreaArr, $areas);
            } else {
                throw new \Exception('提交失败，每个收货地只能设置1个运费');
            }
        }
        $shippingPlace = json_decode($shippingPlace, true);
        $shippingPlace = $shippingPlace ? implode(',', $shippingPlace) : '';
        $supportArea = json_decode($supportArea, true);
        $supportArea = $supportArea ? implode(',', $supportArea) : '';
        if (!$templId) {//新添加运费模板
            return self::addTempl($uid, $shopId, $name, $billingCate, $billingUit, $shippingPlace, $supportArea, $shippingPrice);
        } else {//编辑运费模板
            self::updateTempl($templId, $uid, $shopId, $name, $billingCate, $billingUit, $shippingPlace, $supportArea, $shippingPrice);
            return true;
        }
    }


    /**
     * 添加运费模板
     * @param $uid
     * @param $shopId
     * @param $name
     * @param $billingCate
     * @param $billingUit
     * @param $shippingPlace
     * @param $supportArea
     * @param array $shippingPrice
     * @return bool
     * @throws \Exception
     */
    public static function addTempl($uid, $shopId, $name, $billingCate, $billingUit, $shippingPlace, $supportArea, array $shippingPrice)
    {
        $result = ShippingTemplModel::action(function () use ($uid, $shopId, $name, $billingCate, $billingUit, $shippingPlace, $supportArea, $shippingPrice) {
            $templId = ShippingTemplModel::addTempl([
                'uid' => $uid,
                'shop_id' => $shopId,
                'name' => $name,
                'billing_cate' => $billingCate,
                'billing_unit' => $billingUit,
                'shipping_place' => $shippingPlace,
                'support_area' => $supportArea,
            ]);
            $attrData = [
                'uid' => $uid,
                'shop_id' => $shopId,
                'templ_id' => $templId,
                'addtime' => date("Y-m-d H:i:s")
            ];
            if ($shippingPrice) {
                $data = [];
                $isExitDefault = false;
                foreach ($shippingPrice as $row) {
                    if (($row['base_price'] == 0 && $row['continued_price'] == 0) || (!$row['base_price'] && !$row['continued_price'])) {
                        $row['type'] = ShippingTemplAttrModel::TYPE_FREE;
                    } else {
                        $row['type'] = ShippingTemplAttrModel::TYPE_NOFREE;
                    }
                    $attrData['type'] = $row['type'];
                    $attrData['area'] = self::implodeAreaCode($row['area']);
                    $attrData['base'] = $row['base'];
                    $attrData['base_price'] = $row['base_price'];
                    $attrData['continued'] = $row['continued'];
                    $attrData['continued_price'] = $row['continued_price'];
                    $attrData['is_default'] = isset($row['is_default']) ? $row['is_default'] : 0;
                    if (isset($row['is_default']) && $row['is_default']) {
                        $isExitDefault = true;
                    }
                    $data[] = $attrData;
                }
                if ($data) {
                    if ($isExitDefault) {
                        ShippingTemplAttrModel::addAttrs($data);
                    } else {
                        throw new \Exception('请设置一个默认邮费方案');
                    }
                }
            } else {//默认地区
                $data = $attrData;
                $data['type'] = 1;
                $data['is_default'] = 1;
                ShippingTemplAttrModel::addAttr($data);
            }
            return true;
        });
        return $result;
    }


    /**
     * 编辑运费模板
     * @param $templId
     * @param $uid
     * @param $shopId
     * @param $name
     * @param $billingCate
     * @param $billingUit
     * @param $shippingPlace
     * @param $supportArea
     * @param array $shippingPrice
     * @return mixed
     */
    public static function updateTempl($templId, $uid, $shopId, $name, $billingCate, $billingUit, $shippingPlace, $supportArea, array $shippingPrice)
    {
        $result = ShippingTemplModel::action(function () use ($templId, $uid, $shopId, $name, $billingCate, $billingUit, $shippingPlace, $supportArea, $shippingPrice) {
            ShippingTemplModel::updateTempl([
                'name' => $name,
                'billing_cate' => $billingCate,
                'billing_unit' => $billingUit,
                'shipping_place' => $shippingPlace,
                'support_area' => $supportArea,
            ], [
                'id' => $templId,
                'shop_id' => $shopId
            ]);
            if ($shippingPrice) {
                $attrArr = ShippingTemplAttrModel::getByTemplId($templId, ShippingTemplAttrModel::STATUS_PASSED);
                $isExitDefault = false;
                $isDefaultAttrId = 0;
                if ($attrArr) {
                    $attrList = [];
                    foreach ($attrArr as $row) {
                        $attrList[$row['id']] = $row;
                        if ($row['is_default'] == 1) {
                            $isExitDefault = true;
                            $isDefaultAttrId = $row['id'];
                        }
                    }
                }
                $attrIds = array_keys($attrList);
                $insertData = [
                    'uid' => $uid,
                    'shop_id' => $shopId,
                    'templ_id' => $templId,
                    'addtime' => date('Y-m-d H:i:s')
                ];
                $attrChangeIds = [];
                foreach ($shippingPrice as $row) {
                    if (($row['base_price'] == 0 && $row['continued_price'] == 0) || (!$row['base_price'] && !$row['continued_price'])) {
                        $row['type'] = ShippingTemplAttrModel::TYPE_FREE;
                    } else {
                        $row['type'] = ShippingTemplAttrModel::TYPE_NOFREE;
                    }
                    $attrId = isset($row['attr_id']) ? $row['attr_id'] : 0;
                    array_push($attrChangeIds, $attrId);
                    if ($attrId && $attrList && isset($attrList[$attrId])) {
                        //更新
                        $data['type'] = $row['type'];
                        $data['area'] = self::implodeAreaCode($row['area']);
                        $data['status'] = ShippingTemplAttrModel::STATUS_PASSED;
                        if (isset($row['is_default']) && $row['is_default'] && $attrId != $isDefaultAttrId) {
                            throw new \Exception('已经存在一个默认邮费设置');
                        }
                        $data['base'] = $row['base'];
                        $data['base_price'] = $row['base_price'];
                        $data['continued'] = $row['continued'];
                        $data['continued_price'] = $row['continued_price'];
                        $data['is_default'] = isset($row['is_default']) ? $row['is_default'] : 0;
                        ShippingTemplAttrModel::updateAttr($data, ['id' => $attrId, 'shop_id' => $shopId]);
                    } else {
                        //添加
                        $data = $insertData;
                        $data['type'] = $row['type'];
                        $data['area'] = self::implodeAreaCode($row['area']);
                        if ($isExitDefault && isset($row['is_default']) && $row['is_default'] == 1) {
                            throw new \Exception('已经存在一个默认邮费设置');
                        }
                        if ($row['type'] == ShippingTemplAttrModel::TYPE_NOFREE) {
                            $data['base'] = $row['base'];
                            $data['base_price'] = $row['base_price'];
                            $data['continued'] = $row['continued'];
                            $data['continued_price'] = $row['continued_price'];
                            $data['is_default'] = isset($row['is_default']) ? $row['is_default'] : 0;
                        }
                        ShippingTemplAttrModel::addAttr($data);
                    }
                }
                //删除
                $delAttrIds = array_diff($attrIds, $attrChangeIds);
                foreach ($delAttrIds as $delId) {
                    ShippingTemplAttrModel::updateAttr(['status' => ShippingTemplAttrModel::STATUS_DELETE], ['id' => $delId, 'is_default' => 0, 'shop_id' => $shopId]);
                }
            }
            return true;
        });
        return $result;
    }

    /**
     * 如果有市级code则去掉省级code(永远排除商家后台传过来的包邮地区)
     * @param $areaCodes
     * @param $isImplode
     * @return string | array
     */
    public static function implodeAreaCode($areaCodes, $isImplode = true)
    {
        $superCityCodes = ['110000', '120000', '310000', '500000'];
        $result = [];
        foreach ($areaCodes as $areaCode) {
            $areaCodeArr = ShopArea::getAreaCodeArr($areaCode);
            if ($areaCodeArr) {
                $provinceCode = $areaCodeArr[0];
                $cityCode = $areaCodeArr[1];
                if (in_array($provinceCode, $superCityCodes)) {//如果是直辖市，直接返回省级code
                    $result[$provinceCode] = [];
                } else {
                    if ($areaCode == $provinceCode) {
                        if (!isset($result[$provinceCode])) {
                            $result[$provinceCode] = [];
                        }
                    } else if ($areaCode == $cityCode) {
                        $result[$provinceCode][] = $cityCode;
                    }
                }
            }
        }
        $arr = [];
        //如果包即含省又包含省下面的市，则只返回市
        foreach ($result as $province => $row) {
            if ($row) {
                $arr = array_merge($arr, $row);
            } else {
                $arr = array_merge($arr, [(string)$province]);
            }
        }
        if ($isImplode) {
            return $arr ? implode(',', $arr) : '';
        } else {
            return $arr;
        }
    }

    public static function delTempl($templId, $shopId)
    {
        $goodsIds = GoodsExtendInfo::getGoodsIdsByShippingTemplId($templId);
        if ($goodsIds) {
            if ($goodsIds && GoodsBasicInfo::hasShippingTemplGoodsIds($goodsIds)) {
                throw new \Exception('该模板已被商品占用，不能删除');
            }
        }
        $result = ShippingTemplModel::action(function () use ($templId, $shopId) {
            ShippingTemplModel::updateTempl(['status' => ShippingTemplModel::STATUS_DELETE], ['id' => $templId, 'shop_id' => $shopId]);
            ShippingTemplAttrModel::updateAttr(['status' => ShippingTemplAttrModel::STATUS_DELETE], ['templ_id' => $templId, 'shop_id' => $shopId]);
            return true;
        });
        return $result;
    }


    public static function getTemplById($templId, $attr = true)
    {
        $tempInfo = ShippingTemplModel::getTemplInfoById($templId, ShippingTemplAttrModel::STATUS_PASSED);
        if ($tempInfo && $attr) {
            $tempInfo['shipping_place_name'] = ShopArea::locationId2String($tempInfo['shipping_place']);
            $tempInfo['support_area_name'] = $tempInfo['support_area'] ? ShopArea::locationId2String($tempInfo['support_area']) : '不限制';
            $attrArr = ShippingTemplAttrModel::getByTemplId($templId, ShippingTemplAttrModel::STATUS_PASSED, ['is_default' => 'DESC', 'type' => 'ASC']);
            foreach ($attrArr as &$row) {
                $row['area_id'] = $row['area'] ? explode(",", $row['area']) : [];
                $row['area_name'] = $row['area'] ? ShopArea::locationId2Array($row['area']) : [];
                $row['type_desc'] = $row['type'] == ShippingTemplAttrModel::TYPE_FREE ? '包邮地区' : '非包邮地区';
            }
            $tempInfo['attr'] = $attrArr;
        }
        return $tempInfo;
    }

    /**
     * 查询地区基础运费
     * @param array $templIdsArr 运费模板id对应的重量和体积
     * @param string $areaCode 地区code码（provinceCode/cityCode）
     * @return array
     */
    public static function quickGetShippingInfos($templIdsArr, $areaCode)
    {
        $templIds = array_keys($templIdsArr);
        $currAreaCodeArr = ShopArea::getAreaCodeArr($areaCode);
        $provinceCode = null;
        $cityCode = null;
        if ($currAreaCodeArr) {
            $provinceCode = $currAreaCodeArr[0];
            $cityCode = $currAreaCodeArr[1];
        }
        list($shippingTemplInfos, $noCacheKeys) = cShipping::quickGetShippingInfos($templIds);
        if ($noCacheKeys) {
            $mShippingTempls = ShippingTemplModel::getTemplinfos($noCacheKeys);
            $shippingData = [];
            foreach ($mShippingTempls as $shippingTemplId => $shippingTempl) {
                foreach ($shippingTempl['list'] as $shippingTemplAttr) {
                    if (!isset($defaultData['shipping_address'])) {
                        $defaultData = [
                            'shipping_address' => $shippingTempl['shipping_address'],
                            'bill_cate' => $shippingTempl['billing_cate'],
                            'base' => 0,
                            'base_price' => 0,
                            'continued' => 0,
                            'continued_price' => 0,
                        ];
                    }
                    if ($shippingTemplAttr['is_default']) {
                        $defaultData = [
                            'shipping_address' => $shippingTempl['shipping_address'],
                            'bill_cate' => $shippingTempl['billing_cate'],
                            'base' => $shippingTemplAttr['base'],
                            'base_price' => $shippingTemplAttr['base_price'],
                            'continued' => $shippingTemplAttr['continued'],
                            'continued_price' => $shippingTemplAttr['continued_price'],
                        ];
                    }
                    $shippingData[$shippingTemplId][cShipping::DEFAULE_INFO_KEY] = $defaultData;
                    if ($shippingTemplAttr['area']) {
                        $areas = explode(',', $shippingTemplAttr['area']);
                        foreach ($areas as $area) {
                            $areaCodeArr = ShopArea::getAreaCodeArr($area);
                            if ($areaCodeArr) {
                                $areaCodeProvince = $areaCodeArr[0];
                                $areaCodeCity = $areaCodeArr[1];
                                $shippingData[$shippingTemplId][$areaCodeProvince] = [
                                    'shipping_address' => $shippingTempl['shipping_address'],
                                    'bill_cate' => $shippingTempl['billing_cate'],
                                    'base' => $shippingTemplAttr['base'],
                                    'base_price' => $shippingTemplAttr['base_price'],
                                    'continued' => $shippingTemplAttr['continued'],
                                    'continued_price' => $shippingTemplAttr['continued_price'],
                                ];

                                if (!isset($shippingData[$shippingTemplId][$areaCodeProvince]['city'])) {
                                    $shippingData[$shippingTemplId][$areaCodeProvince]['city'] = [];
                                }
                                if ($areaCodeCity) {
                                    $shippingData[$shippingTemplId][$areaCodeProvince]['city'][] = $areaCodeCity;
                                }
                            }
                        }
                    }
                }
            }
            cShipping::setShippingInfos($shippingData);
            $shippingTemplInfos = $shippingTemplInfos + $shippingData;
        }
        $shippingInfos = [];
        foreach ($templIdsArr as $templId => $goodsArrs) {
            foreach ($goodsArrs as $goodsId => $goodsArr) {
                $weight = $goodsArr['weight'];
                $volume = $goodsArr['volume'];
                if (isset($shippingTemplInfos[$templId])) {
                    if (isset($shippingTemplInfos[$templId][$provinceCode])) {
                        $info = $shippingTemplInfos[$templId][$provinceCode];
                        if ($info['city']) {//如果运费模板设置到市级
                            if ($areaCode == $cityCode && in_array($areaCode, $info['city'])) {
                                $price = self::getSimpleShippingPrice($info['base'], $info['base_price'], $info['continued'], $info['continued_price'], $info['bill_cate'], $weight, $volume);
                                $shippingInfos[$goodsId] = [
                                    'shipping_address' => $shippingTemplInfos[$templId][cShipping::DEFAULE_INFO_KEY]['shipping_address'],
                                    'price' => $price
                                ];
                            } else {
                                $info = $shippingTemplInfos[$templId][cShipping::DEFAULE_INFO_KEY];
                                $price = self::getSimpleShippingPrice($info['base'], $info['base_price'], $info['continued'], $info['continued_price'], $info['bill_cate'], $weight, $volume);
                                $shippingInfos[$goodsId] = [
                                    'shipping_address' => $shippingTemplInfos[$templId][cShipping::DEFAULE_INFO_KEY]['shipping_address'],
                                    'price' => $price
                                ];
                            }
                        } else {//运费模板值设置到省级
                            $price = self::getSimpleShippingPrice($info['base'], $info['base_price'], $info['continued'], $info['continued_price'], $info['bill_cate'], $weight, $volume);
                            $shippingInfos[$goodsId] = [
                                'shipping_address' => $shippingTemplInfos[$templId][cShipping::DEFAULE_INFO_KEY]['shipping_address'],
                                'price' => $price
                            ];
                        }
                    } else {
                        $info = $shippingTemplInfos[$templId][cShipping::DEFAULE_INFO_KEY];
                        $price = self::getSimpleShippingPrice($info['base'], $info['base_price'], $info['continued'], $info['continued_price'], $info['bill_cate'], $weight, $volume);
                        $shippingInfos[$goodsId] = [
                            'shipping_address' => $shippingTemplInfos[$templId][cShipping::DEFAULE_INFO_KEY]['shipping_address'],
                            'price' => $price
                        ];
                    }
                } else {
                    $shippingInfos[$goodsId] = [
                        'shipping_address' => "未知",
                        'price' => '0.00'
                    ];
                }
            }
        }
        return $shippingInfos;
    }

    private static function getSimpleShippingPrice($base, $basePrice, $continued, $continuedPrice, $billCate = 1, $weight = 0, $volume = 0)
    {
        if ($billCate == ShippingTemplModel::BILLING_CATE_PIECES) {//按件计费
            return $basePrice;
        } else if ($billCate == ShippingTemplModel::BILLING_CATE_WEIGHT) {//按重量计费
            return self::_computerShippingPrice($weight, $base, $basePrice, $continued, $continuedPrice);
        } else if ($billCate == ShippingTemplModel::BILLING_CATE_VOLUME) {//按体积计费
            return self::_computerShippingPrice($volume, $base, $basePrice, $continued, $continuedPrice);
        }
    }

    private static function _computerShippingPrice($current, $base, $basePrice, $continued, $continuedPrice)
    {
        if ($current) {
            if ($current <= $base || $base == 0) {
                $price = $basePrice;
            } else {
                if ($continued > 0) {
                    $price = $basePrice;
                    $_continue = ceil(bcadd(($current - $base) / $continued, 0, 2));
                    $_continuePrice = bcmul($_continue, $continuedPrice, 2);
                    $price = bcadd($price, $_continuePrice, 2);
                } else {
                    $price = $basePrice;
                    $price = bcadd($price, $continuedPrice, 2);
                }
            }
        } else {
            $price = $basePrice;
        }
        return $price;
    }

    /**
     * 根据运费模板id获取默认运费
     * @param $shippingTemplIds
     * @param $areaCode
     * @return array
     */
    public static function getDefaultShippingPrice($shippingTemplIds, $areaCode, $uid)
    {
        $defaultCityCode = UserAddress::getUserDefaultCityCode($uid);

        $shippingList = ShippingTemplModel::getTemplinfos($shippingTemplIds);

        return array_map(function ($templInfo) use ($defaultCityCode, $areaCode) {
            $defaultProvinceCode = '';
            if ($defaultCityCode) {
                $defaultAreaCodeArr = ShopArea::getAreaCodeArr($defaultCityCode);
                $defaultProvinceCode = $defaultAreaCodeArr[0];
            }
            $areaCodeArr = ShopArea::getAreaCodeArr($areaCode);
            $provinceId = $areaCodeArr[0];
            $cityId = $areaCodeArr[1];
            if ($defaultProvinceCode || $defaultCityCode)
                foreach ($templInfo['list'] as $shippingTemplAttr) {
                    $area = explode(',', $shippingTemplAttr['area']);
                    if (in_array($defaultProvinceCode, $area) || in_array($defaultCityCode, $area)) {
                        return $shippingTemplAttr['base_price'];
                    }
                }
            reset($templInfo['list']);

            if ($provinceId || $cityId)
                foreach ($templInfo['list'] as $shippingTemplAttr) {
                    $area = explode(',', $shippingTemplAttr['area']);
                    if (in_array($provinceId, $area) || in_array($cityId, $area)) {
                        return $shippingTemplAttr['base_price'];
                    }
                }

            return ShippingTemplAttrModel::getDefaultPrice($templInfo['list'][0]['templ_id']);

        }, $shippingList);
    }


    /**
     * 检查收货地址是否在商品的配送范围
     * @param array $goodsShippingTemplArr 商品id对应的运费模版id['goods_id'=>['shipping_templ_id'=>309]...]
     * @param $areaCode 收货地区code
     * @return bool
     */
    public static function checkGoodsSupportShipping($goodsShippingTemplArr, $areaCode)
    {
        $result = [
            'support' => true,
            'support_goods' => [],
            'nonsupport_goods' => [],
            'support_area' => []
        ];

        $areaCodeArr = ShopArea::getAreaCodeArr($areaCode);
        $provinceId = isset($areaCodeArr[0]) ? $areaCodeArr[0] : 0;
        $cityId = isset($areaCodeArr[1]) ? $areaCodeArr[1] : 0;

        $shippingTemplIds = [];
        $goodsShippingTemplList = [];
        foreach ($goodsShippingTemplArr as $goodsId => $row) {
            $shippingTemplIds[] = $row['shipping_templ_id'];
            $goodsShippingTemplList[$goodsId] = $row['shipping_templ_id'];
        }
        $supportAreaArr = self::getSupportArea($shippingTemplIds);
        $supportShipping = true;
        foreach ($goodsShippingTemplList as $goodsId => $shippingTemplId) {
            $supportArea = isset($supportAreaArr[$shippingTemplId]) ? $supportAreaArr[$shippingTemplId] : [];
            if ($supportArea) {
                if (in_array($provinceId, $supportArea) || in_array($cityId, $supportArea)) {
                    array_push($result['support_goods'], $goodsId);
                } else {
                    array_push($result['nonsupport_goods'], $goodsId);
                    $supportShipping = false;
                }
                $supportAreaName = ShopArea::locationId2Array(implode(',', $supportArea));
                $result['support_area'][$goodsId] = implode(' ', $supportAreaName);
                $result['support_area_code'][$goodsId] = $supportArea;
            } else {
                array_push($result['support_goods'], $goodsId);
            }
        }

        $result['support'] = $supportShipping;

        return $result;
    }

    public static function getSupportArea($shippingTemplIds)
    {
        $supportAreas = ShippingTemplModel::getSupportAreas($shippingTemplIds);
        return $supportAreas;
    }
}